﻿/**
 * Licensed to Open-Ones Group under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Open-Ones Group licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a
 * copy of the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
namespace IPresenter
{
    using System;
    using System.Collections.Generic;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;
    using System.Windows.Forms;

    /// <summary>
    /// Class is used to execute related process to Client
    /// </summary>
    public class ClientIPresenter
    {
        /// <summary>
        /// List of file powerpoint are running on PC
        /// </summary>
        private List<string> lstFilePresentation;

        /// <summary>
        /// Socket use to send and receive message
        /// </summary>
        private Socket skClient;

        /// <summary>
        /// Name of computer whose you want to connect.
        /// </summary>
        private string strHostName;

        /// <summary>
        /// Gets or sets List of file powerpoint are running on pC
        /// </summary>
        public List<string> FilesPresentation
        {
            get { return this.lstFilePresentation; }
            set { this.lstFilePresentation = value; }
        }

        /// <summary>
        /// Gets or sets Socket Device
        /// </summary>
        public Socket ClientDevice
        {
            get { return this.skClient; }
            set { this.skClient = value; }
        }
     
        /// <summary>
        /// Gets or sets Host Name
        /// </summary>
        public string HostName
        {
            get { return this.strHostName; }
            set { this.strHostName = value; }
        }

        /// <summary>
        /// Setup connection from client to server
        /// </summary>
        /// <param name="hostName">Host name of computer</param>
        /// <returns>
        /// true: success
        /// false: fail
        /// </returns>
        public bool Init(string hostName)
        {
            try
            {
                this.strHostName = hostName;
                this.skClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                this.skClient.Connect(this.strHostName, 3333);
                this.lstFilePresentation = new List<string>();
                HookProvider.RegisterHook();
                HookProvider.VirtualKeyDownDelegate = new HookProvider.GetKeyDownEventHandler(this.ReceiveKeyDown);
            }
            catch (Exception ex)
            {
                Logs.WriteErrorMessage(ex.Message);
                return false;
            }

            return true;
        }

        /// <summary>
        /// Abort connection to server
        /// </summary>
        public void Dispose()
        {
            Threads.Dispose();
            try
            {
                this.skClient.Close();
            }
            catch (Exception ex)
            {
                Logs.WriteErrorMessage(ex.Message);
            }
        }

        /// <summary>
        /// Recevice event keydown from client
        /// </summary>
        /// <param name="command">Name of Command</param>
        public void ReceiveKeyDown(string command)
        {
            try
            {
                int intSizeClassName = 0;
                int intHWnd = ApiFunction.GetForegroundWindow();
                StringBuilder strBuilderClassName = new StringBuilder(255);
                intSizeClassName = ApiFunction.GetClassName(intHWnd, strBuilderClassName, 255);
                if (intSizeClassName == 0)
                {
                    return;
                }

                if (strBuilderClassName.ToString() == "Shell_TrayWnd")
                {
                    if (command == PresentCommand.GO_TO_SLIDE)
                    {
                        command = string.Empty;
                        if (HookProvider.KeyPressedList[0] == 0)
                        {
                            HookProvider.KeyPressedList.RemoveAt(0);
                        }

                        for (int i = 0; i < HookProvider.KeyPressedList.Count; i++)
                        {
                            command += (HookProvider.KeyPressedList[i] - 48).ToString();
                        }
                    }

                    NetworkSupport.SendMessageAscii(this.ClientDevice, command);
                    HookProvider.KeyPressedList.Clear();
                }
            }
            catch (Exception ex)
            {
                Logs.WriteErrorMessage(ex.Message);
            }
        }

        /// <summary>
        /// Client always listen and receive message.
        /// </summary>
        public void Connect()
        {
            try
            {
                while (this.skClient.Connected)
                {
                    string strLength;
                    if (OptionIPresenter.Mode == OptionIPresenter.MODE_EXTEND)
                    {
                        NetworkSupport.ReceiveMessageUnicode(this.skClient, out strLength);
                        List<string> lstMessage = new List<string>();
                        NetworkSupport.ReceiveMessageUnicode(this.skClient, out lstMessage, int.Parse(strLength));
                        List<string> lstResult = new List<string>();
                        lstResult = NetworkSupport.AnalysisMessage(lstMessage);
                        this.ExecuteCommand(lstResult);
                    }
                }
            }
            catch (Exception ex)
            {
                Logs.WriteErrorMessage(ex.Message);
            }
        }

        /// <summary>
        /// Executing commands from server
        /// </summary>
        /// <param name="commands">List of command</param>
        private void ExecuteCommand(List<string> commands)
        {
            this.lstFilePresentation.Clear();
            this.lstFilePresentation = commands;
        }
    }
}
